package org.jeecg.modules.workflow.service.oa;


import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.workflow.vo.oa.BpmOALeaveCreateReqVO;
import org.jeecg.common.workflow.vo.oa.BpmOALeavePageReqVO;
import org.jeecg.common.workflow.vo.oa.BpmOALeaveUpdateReqVO;
import org.jeecg.modules.workflow.convert.oa.BpmOALeaveConvert;
import org.jeecg.modules.workflow.entity.BpmOaLeave;
import org.jeecg.modules.workflow.enums.task.BpmProcessInstanceResultEnum;
import org.jeecg.modules.workflow.mapper.BpmOaLeaveMapper;
import org.jeecg.modules.workflow.service.task.BpmProcessInstanceService;
import org.jeecg.modules.workflow.service.task.BpmTaskService;
import org.jeecg.modules.workflow.service.task.dto.BpmProcessInstanceCreateReqDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static org.jeecg.common.exception.util.ServiceExceptionUtil.exception;
import static org.jeecg.modules.workflow.enums.ErrorCodeConstants.OA_LEAVE_NOT_EXISTS;

/**
 * OA 请假申请 Service 实现类
 *
 * @author jason
 * @author 芋道源码
 */
@Service
@Validated
public class BpmOALeaveServiceImpl implements BpmOALeaveService {


    /**
     * OA 请假对应的流程定义 KEY
     */
    public static final String PROCESS_KEY = "oa_leave";

    @Resource
    private BpmOaLeaveMapper leaveMapper;

    @Resource
    private BpmProcessInstanceService processInstanceApi;

    @Autowired
    BpmOALeaveConvert bpmOALeaveConvert;

    @Autowired
    private BpmTaskService bpmTaskService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createLeave(String userId, BpmOALeaveCreateReqVO createReqVO) {
        // 插入 OA 请假单
        long day = DateUtil.betweenDay(createReqVO.getStartTime(), createReqVO.getEndTime(), false);
        BpmOaLeave leave = bpmOALeaveConvert.convert(createReqVO);
        leave.setUserId(userId);
        leave.setDay((int)day);
        leave.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
        leave.setCreateBy(getUserName());
        leave.setCreateTime(new Date());
        leaveMapper.insert(leave);

        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        processInstanceVariables.put("day", day);
        BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
        bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(PROCESS_KEY);
        bpmProcessInstanceCreateReqDTO.setVariables(processInstanceVariables);
        bpmProcessInstanceCreateReqDTO.setBusinessKey(String.valueOf(leave.getId()));
        String processInstanceId = processInstanceApi.createProcessInstance(userId,bpmProcessInstanceCreateReqDTO);

        // 将工作流的编号，更新到 OA 请假单中
        BpmOaLeave bpmOaLeaveUpdate = new BpmOaLeave();
        bpmOaLeaveUpdate.setId(leave.getId());
        bpmOaLeaveUpdate.setProcessInstanceId(processInstanceId);
        bpmOaLeaveUpdate.setUpdateBy(getUserName());
        bpmOaLeaveUpdate.setUpdateTime(new Date());
        leaveMapper.updateById(bpmOaLeaveUpdate);
        return leave.getId();
    }

    @Override
    public void updateLeaveResult(String id, Integer result) {
        validateLeaveExists(id);
        BpmOaLeave bpmOaLeaveUpdate = new BpmOaLeave();
        bpmOaLeaveUpdate.setId(id);
        bpmOaLeaveUpdate.setResult(result);
        bpmOaLeaveUpdate.setUpdateBy(getUserName());
        bpmOaLeaveUpdate.setUpdateTime(new Date());
        leaveMapper.updateById(bpmOaLeaveUpdate);
    }

    private void validateLeaveExists(String id) {
        if (leaveMapper.selectById(id) == null) {
            throw exception(OA_LEAVE_NOT_EXISTS);
        }
    }

    @Override
    public BpmOaLeave getLeave(String id) {
        return leaveMapper.selectById(id);
    }

    @Override
    public IPage<BpmOaLeave> getLeavePage(String userId, BpmOALeavePageReqVO pageReqVO) {
        return leaveMapper.selectPage(userId, pageReqVO);
    }

    private String getUserName()
    {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        return sysUser.getRealname();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLeave(String userId, BpmOALeaveUpdateReqVO updateReqVO) {
        long day = DateUtil.betweenDay(updateReqVO.getStartTime(), updateReqVO.getEndTime(), false);
        BpmOaLeave leave = bpmOALeaveConvert.convert(updateReqVO);
        leave.setId(updateReqVO.getId());
        leave.setUserId(userId);
        leave.setDay((int)day);
        leave.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
        leave.setCreateBy(getUserName());
        leave.setCreateTime(new Date());
        leaveMapper.updateById(leave);

        Map<String, Object> processInstanceVariables = new HashMap<>();
        processInstanceVariables.put("day", day);
        bpmTaskService.updateBusinessFormFlow(userId,updateReqVO.getTaskId(), processInstanceVariables);

    }
}
